package com.hm.uums.controller;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.hm.common.Constant;
import com.hm.common.annotation.Function;
import com.hm.common.api.ApiResult;
import com.hm.common.api.ApiStatus;
import com.hm.common.enums.Authority;
import com.hm.common.utils.DateUtils;
import com.hm.common.utils.MD5Utils;
import com.hm.common.utils.RSAEncryptUtils;
import com.hm.common.utils.StringUtils;
import com.hm.common.utils.TokenUtils;
import com.hm.uums.service.CommonService;
import com.hm.uums.service.ParmService;
import com.hm.uums.utils.ClientUtils;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

/**
 * @author hwg
 *
 *         2020年12月18日 公共接口部分，完成一些公共的接口，如登录、退出、token校验等。
 */
@Api(tags = "1.公共接口部分")
@RestController
@RequestMapping("/common")
public class CommonController extends BaseController {
	Logger logger = LoggerFactory.getLogger(CommonController.class);

	@Autowired
	private CommonService commonService;

	@Autowired
	private ParmService parmService;

	/**
	 * 登录接口，校验携带的用户名和密码，用户登录成功后，生成token，记录登录信息到数据库中
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ApiOperation("登录")
	@ApiImplicitParams({//
			@ApiImplicitParam(name = "username", value = "登录用户名", required = true, dataType = "String", paramType = "query"), //
			@ApiImplicitParam(name = "password", value = "登录密码", required = true, dataType = "String", paramType = "query")//
	})
	@PostMapping("/login")
	@Function(module = "uums", code = "uums.common.login", description = "登录", authority = Authority.UNREQUIRE_LOGIN)
	public ApiResult login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String reqId = getReqId(request);//请求Id
		String username = request.getParameter("username");//用户名
		String password = request.getParameter("password");//密码

		//用户名密码不能为空
		if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
			return ApiResult.of(reqId, ApiStatus.STATUS_1002, request.getRequestURI());
		}

		//把密码转换为MD5，查找是否存在此用户
		Map<String, Object> mData = commonService.findUsers(username, MD5Utils.encode(password));

		//不存在用户，返回登录失败
		if (StringUtils.isEmpty(mData)) {
			return ApiResult.of(reqId, ApiStatus.STATUS_1000, request.getRequestURI());
		}

		//验证用户状态，0为正常，1为禁用
		int status = (int) mData.get("status");
		if (status == 1) {
			return ApiResult.of(reqId, ApiStatus.STATUS_1001, request.getRequestURI());
		}

		//用户token超时时间。用户超过指定时间未次访问系统，则token失效，再次访问需要重新认证！未配置或配置错误（非数字、0或负数等），则默认为30分钟
		int tokenTimeoutMinutes = StringUtils.toInt(parmService.getParmValueByKey("token-timeout-minutes"), 30);
		//同一个用户是否允许多个客户端同时登录在线操作，0：不允许，1：允许！未配置或配置错误（非0和1），则默认为0
		int allowMultipleClientOnline = StringUtils.toInt(parmService.getParmValueByKey("allow-multiple-client-online"), 0);

		//用户token超时时间必须大于0，小于等于0，则强制设置为30分钟
		if (tokenTimeoutMinutes <= 0) {
			tokenTimeoutMinutes = 30;
		}

		//如果设置的值不是0或1，则强制设置为0不允许
		if (!(allowMultipleClientOnline == 0 || allowMultipleClientOnline == 1)) {
			allowMultipleClientOnline = 0;
		}

		//得到一个token
		String token = TokenUtils.generateToken();

		//封装用户信息到Map
		Map<String, Object> dMap = new HashMap<String, Object>();
		dMap.put("token", token);
		dMap.put("userId", mData.get("id"));
		dMap.put("tokenTimeoutMinutes", tokenTimeoutMinutes);
		dMap.put("allowMultipleClientOnline", allowMultipleClientOnline);
		dMap.put("clientIp", ClientUtils.getRemoteHostIp(request));
		dMap.put("clientName", ClientUtils.getUserAgent(request));

		//添加用户信息到数据库中
		commonService.addToken(dMap);

		//把用户Id和token添加的响应消息头，作用是在网关处可以得到用户Id等信息记录日志
		response.addHeader(Constant.USER_ID, mData.get("id").toString());
		response.addHeader(Constant.token, token);
		return ApiResult.of(reqId, ApiStatus.STATUS_200, "登录成功", request.getRequestURI(), dMap);
	}

	/**
	 * 用户退出系统，删除token信息，删除之前备份到token历史表
	 * 
	 * @param request
	 * @return
	 */
	@ApiOperation("退出")
	@ApiImplicitParams({//
			@ApiImplicitParam(name = Constant.token, value = "登录接口返回的Token", required = true, dataType = "String", paramType = "header")//
	})
	@DeleteMapping("/logout")
	@Function(module = "uums", code = "uums.common.logout", description = "退出", authority = Authority.UNREQUIRE_LOGIN)
	public ApiResult<String> logout(HttpServletRequest request) {
		String reqId = getReqId(request);//请求Id
		String token = request.getHeader(Constant.token);//token

		commonService.delToken(token);//删除token
		logger.info("Logout succ, token:" + token);
		return ApiResult.of(reqId, ApiStatus.STATUS_200, request.getContextPath(), "退出成功", null);
	}

	/**
	 * 获取系统信息，根据系统编号查找对应的系统信息
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ApiOperation("获取系统信息")
	@ApiImplicitParams({//
			@ApiImplicitParam(name = "sysCode", value = "系统编号", required = true, dataType = "String", paramType = "query")//
	})
	@GetMapping("/sys")
	@Function(module = "uums", code = "uums.common.sys", description = "获取系统信息", authority = Authority.UNREQUIRE_LOGIN)
	public ApiResult getSysInfo(HttpServletRequest request) throws Exception {
		String reqId = getReqId(request);
		String sysCode = request.getParameter("sysCode");

		if (StringUtils.isEmpty(sysCode)) {
			return ApiResult.of(reqId, ApiStatus.STATUS_800, "缺少系统编号sysCode", request.getRequestURI(), null);
		}

		Map<String, Object> dMap = commonService.getSysInfo(Integer.parseInt(sysCode));
		String authCode = StringUtils.toString(dMap.get("authCode"));
		String expireDate = RSAEncryptUtils.decrypt(authCode, Constant.AUTH_CODE_PRIVATE_KEY);
		long expireDateTime = DateUtils.parse(expireDate).getTime();
		long nowTime = DateUtils.now().getTime();
		dMap.put("authCodeStatus", nowTime >= expireDateTime ? 1 : 0);
		dMap.remove("authCode");
		
		return ApiResult.of(reqId, ApiStatus.STATUS_200, "成功", request.getRequestURI(), dMap);
	}

	/**
	 * 验证token
	 * 
	 * @param request
	 * @return
	 */
	@ApiOperation("验证token")
	@ApiImplicitParams({//
			@ApiImplicitParam(name = Constant.token, value = "登录接口返回的Token", required = true, dataType = "String", paramType = "header")//
	})
	@GetMapping("/validateToken")
	@Function(module = "uums", code = "uums.common.validate.token", description = "验证token", authority = Authority.UNREQUIRE_LOGIN)
	public ApiResult<String> validateToken(HttpServletRequest request) {
		String reqId = getReqId(request);//请求Id
		String token = getToken(request);//token
		if (commonService.validateToken(token)) {//查找验证token
			return ApiResult.of(reqId, ApiStatus.STATUS_200, request.getContextPath());
		}
		return ApiResult.of(reqId, ApiStatus.STATUS_600, request.getContextPath());
	}

}
